/**
    \class Pedestrian

    \brief Obiekt pieszego.

    Pieszy jest reprezentowany jako seledynowe kółko. W momencie stworzenia zacznie przesuwać się w stronę _endPoint ze stałą prędkością. W sposób ograniczony potrafi omijać przeszkody, ale zawsze będzie to robił skręcając w jedną stronę. Po dotarciu do końca drogi, uruchamiany jest destruktor.
  */
#include "pedestrian.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsScene>
#include <QDebug>

/**
    \param startPoint miejsce "spawnu" pieszego.
    \param endPoint cel wędrówki pieszego.
    \param speed Prędkość pieszego. O tyle pikseli przesunie się w jednej klatce.

    Parametry x, y, w, h określają rozmiar elipsy, którą reprezentowany jest pieszy i są bezpośrednio przekazywane do konstruktora QGraphicsEllipseItem.
  */
Pedestrian::Pedestrian(QPointF startPoint, QPointF endPoint, qreal x, qreal y, qreal w, qreal h, qreal speed)
    :QGraphicsEllipseItem(x, y, w, h), _speed(speed), _endPoint(endPoint)
{
    setPos(mapToParent(startPoint));
    //trzeba by go odwrócić przodem do kierunku marszu...

    QLineF marchLine (mapFromParent(startPoint), mapFromParent(endPoint));
    QLineF myLine(mapFromParent(startPoint), QPointF(0, -w/2));

    rotate(180 - myLine.angleTo(marchLine)); // obracam pieszego przodem do celu

    _rotated = false;
}
/**
    Rysujemy seledynowe kołko. Od centrum koła w "górę" (w stronę kierunku marszu) rysuję białą linię, by widać by było gdzie pieszy ma przód, a gdzie tył.
  */
void Pedestrian::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
    painter->setClipRect( option->exposedRect );
    QBrush brush(Qt::SolidPattern);
    brush.setColor(Qt::cyan);
    painter->setBrush(brush);
    painter->drawEllipse(rect());

    brush.setColor(Qt::white);
    QPen pen(brush, 1);
    pen.setColor(Qt::white);
    painter->setPen(pen);
    painter->drawLine(QLineF(0, 0, 0, rect().width()/2)); // znacznik kierunku pieszego
}

/**
    \brief Animacja pieszego.

    Jeżeli pieszy z niczym widocznym nie koliduje, to po prostu odwraca się w stronę swojego celu i maszeruje naprzód.
    W przeciwnym wypadku, obraca się w stronę, gdzie nie ma przeszkód.
  */
void Pedestrian::advance(int step)
{
    if (!step)
        return;

    qreal w = rect().width()/2;

    QLineF marchLine (QPointF(0, 0), mapFromParent(_endPoint));
    QLineF myLine(QPointF(0, 0), QPointF(0, -w/2));

//    _rotated = false;

    QPainterPath path(QPointF(0, 0));
    path.lineTo(w, 0);
    path.lineTo(w, w);
    path.lineTo(-w, w);
    path.lineTo(-w, 0);

    QList<QGraphicsItem *> items = scene()->items(mapToParent(path));
    foreach (QGraphicsItem* item, items)
    {
        if ((item->isVisible() == false) || (item == this))
            items.removeOne(item);
        if (Pedestrian *p = dynamic_cast<Pedestrian*>(item))
        {
            Q_UNUSED(p);
            items.removeOne(item);
        }
    }

    if (items.isEmpty())
    {
        rotate(180 - myLine.angleTo(marchLine)); // obracam pieszego przodem do celu
        setPos(mapToParent(0, _speed));
    }
    else
    {
        QPointF detector(-2*w, w+2);  // linia na wprost; początek od lewej strony
        QLineF line(QPointF(0, 0), detector);
        for (int i = 0; i < 360; i = i + 60)
        {
            line.setAngle(i - 90);  // to przesuwa tylko drugi punkt w linii (czyli detector)
            if (scene()->itemAt(mapToParent(line.p2())) == 0) // jeżeli w jakś stronę nie ma żadnego obiektu
            {
                setRotation(rotation() - i); // obróćmy się tam!
                break;
            }
            /**
            \todo Powyższy if nie jest do końca ładny. Po obróceniu się, należałoby sprawdzić jak szybko daną drogą wyjdziemy z kolizji.
             Innymy słowy, ile razy trzeba się przesunąć o _speed, żeby nie kolidować z niczym.
             Zatem lepszy algorytm wyglądałby tak:
                 1) dla każdego obrotu
                    a) policzyć "drogę do wyjścia"
                 2) znaleźć najmniejszą drogą i odpowiadjący jej kąt obrotu
                 3) obrócić się w tą stronę
             */
        }

        setPos(mapToParent(0, _speed));
    }

    if (QLineF(pos(), _endPoint).length() <= 3)
        this->~Pedestrian();
}
/** \see dokumentacja Qt */
QRectF Pedestrian::boundingRect() const
{
//    return QRectF(-2000, -2000, 4000, 4000);  // to się przydaje, jak chcesz narysować coś poza prostokątem samochodu
//    return QRectF(-350, -350, 700, 700);
//    return QRectF(-100, -100, 200, 200);
    return this->rect();
}

/** \see dokumentacja Qt */
QPainterPath Pedestrian::shape() const
{
    QPainterPath path;
    path.addRect(rect());
    return path;
}

Pedestrian::~Pedestrian()
{
    emit(iAmDestroyed());
}
